import os
import cv2
import numpy as np
import matplotlib.pyplot as plt

def clear_directory(directory):
    for filename in os.listdir(directory):
        file_path = os.path.join(directory, filename)
        try:
            if os.path.isfile(file_path) or os.path.islink(file_path):
                os.unlink(file_path)
            elif os.path.isdir(file_path):
                clear_directory(file_path)
        except Exception as e:
            print(f"删除 {file_path} 失败。原因: {e}")
img0 = cv2.imread(r"C:\Users\86183\Desktop\hanzi1.jpg")
height, width, _ = img0.shape
cropped_height = int(height * 0.88)
img0 = img0[height - cropped_height:height, 0:width]

height, width, _ = img0.shape
cropped_height = int(height * 0.95)
img0 = img0[0:cropped_height, 0:width]
img = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)
ret, binary_img = cv2.threshold(img, 100, 5, cv2.THRESH_BINARY)
binary_img = np.bitwise_not(binary_img)

element = cv2.getStructuringElement(cv2.MORPH_CROSS, (4, 4))
eroded_img = cv2.erode(binary_img, element, iterations=2)

element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
dilated_img = cv2.dilate(eroded_img, element, iterations=4)
dilated_img = cv2.medianBlur(dilated_img, 19)

kernel = np.ones((4, 4), np.uint8)
closed_img = cv2.morphologyEx(dilated_img, cv2.MORPH_CLOSE, kernel, iterations=20)

lower = 0
upper = 0
blur_img = cv2.Canny(closed_img, lower, upper)
contours, _ = cv2.findContours(blur_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
fig, ax = plt.subplots(1, 7, figsize=(15, 5))
plt.rcParams['font.sans-serif'] = ['SimHei']

ax[0].imshow(img, cmap='gray')
ax[0].set_title('原图灰度图', fontsize=8)
ax[0].axis('off')

ax[1].imshow(binary_img, cmap='gray')
ax[1].set_title('全局阈值处理>>二值化图', fontsize=8)
ax[1].axis('off')

ax[2].imshow(eroded_img, cmap='gray')
ax[2].set_title('应用腐蚀操作>>去除噪点', fontsize=8)
ax[2].axis('off')

ax[3].imshow(dilated_img, cmap='gray')
ax[3].set_title('应用膨胀操作>>突出图像特征>>中值滤波去除小白点', fontsize=8)
ax[3].axis('off')

ax[4].imshow(closed_img, cmap='gray')
ax[4].set_title('应用闭运算>>填充闭合区域', fontsize=8)
ax[4].axis('off')

ax[5].imshow(blur_img, cmap='gray')
ax[5].set_title('Canny边缘检测', fontsize=8)
ax[5].axis('off')
copy_img = img.copy()
copy_img_color = cv2.cvtColor(copy_img, cv2.COLOR_GRAY2BGR)
chars_dir = 'chars'
if os.path.exists(chars_dir):
    clear_directory(chars_dir)
else:
    os.makedirs(chars_dir)

count = 1
chars_saved = []

for c in contours:
    perimeter = cv2.arcLength(c, True)
    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(img, (x, y), (x + w, y + h), (255), 3)

    if perimeter > 200:
        cv2.rectangle(copy_img_color, (x, y), (x + w, y + h), (20, 255, 20), 3)
        char_img = img0[y:y + h, x:x + w]

        if char_img.tostring() not in chars_saved:
            char_filename = os.path.join(chars_dir, f'{count}.png')
            cv2.imwrite(char_filename, char_img)
            count += 1
            chars_saved.append(char_img.tostring())

ax[6].imshow(copy_img_color)
ax[6].set_title('识别结果', fontsize=8)
ax[6].axis('off')
plt.tight_layout()
plt.show()